home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Nebula 1
/
Nebula One.iso
/
Educational
/
PrimeThreads
/
Source
/
PrimeThreadsApp.m
< prev
Wrap
Text File
|
1995-06-12
|
5KB
|
142 lines
/*********************/
/* PrimeThreadsApp.m */
/*********************/
#import "PrimeThreadsApp.h"
#import <appkit/Button.h>
#import <appkit/Control.h>
#import <appkit/chunk.h>
#import <dpsclient/dpsNeXT.h>
#import <math.h>
/* the code is much smaller when you take out the comments ;-) */
/*
* thePrimeList is maintained by the NXChunk system. GROW_BY
* is how much the structure's malloc'ed space will grow, when
* it needs to be expanded. The chunk is also initialized
* with GROW_BY bytes.
*/
#define GROW_BY 8192
/* every UPDATE_PERIOD seconds, a timed entry calls updateFieldsGlue */
#define UPDATE_PERIOD 0.25
struct primeList {
/* see /usr/include/appkit/chunk.h for a description of the NXChunk */
NXChunk chunk;
/* number of primes in the list */
int numPrimes;
/* This is just a bogus declaration. There can be any number of primes. */
int thePrimes[2];
} *thePrimeList;
/* this mutex guards thePrimeList */
mutex_t primeListLock;
/* this is the function the timed entry calls */
void updateFieldsGlue(DPSTimedEntry te, double now, void *self)
/* we, in turn, call the updateFields method (we're just glue) */
{ [(id)self updateFields]; }
/* findPrimes is executed on its own thread. it never stops. */
void findPrimes(int ignored)
{
int counter, possiblePrime = 5, testLimit;
BOOL isPrime;
while (YES) /* repeat forever */
{
/* isPrime starts at YES. if an exact divisor is found, it becomes NO */
isPrime = YES;
/* for any non-prime integer x, one of its factors is less than sqrt(x) */
testLimit = sqrt(possiblePrime);
for (counter=1; isPrime && (thePrimeList->thePrimes[counter]<=testLimit); counter++)
if (possiblePrime % thePrimeList->thePrimes[counter] == 0)
isPrime = NO;
if (isPrime)
{
/* lock the mutex before changing the list */
mutex_lock(primeListLock);
/* another prime for the list! */
thePrimeList->numPrimes++;
/*
* grow the chunk. usually this does nothing; sometimes more
* space gets allocated.
*/
thePrimeList =
(struct primeList *)NXChunkGrow((NXChunk *)thePrimeList,
thePrimeList->numPrimes * sizeof(int));
/* place our newly-certified prime into the list. */
thePrimeList->thePrimes[thePrimeList->numPrimes - 1] = possiblePrime;
/* unlock the mutex now that we're done with the list */
mutex_unlock(primeListLock);
}
possiblePrime += 2; /* don't bother with even numbers */
/* tell the scheduler that this is a convenient time to run other threads */
cthread_yield();
}
}
@implementation PrimeThreadsApp
/* IB outlets */
- setNumPrimesField:anObject
{ numPrimesField = anObject; return self; }
- setHighestPrimeField:anObject
{ highestPrimeField = anObject; return self; }
- appDidInit:sender
{
/* allocate the mutex */
primeListLock = mutex_alloc();
/*
* initialize thePrimeList with GROW_BY bytes of memory
* to start with, and make it grow by GROW_BY bytes when
* it expands.
*/
thePrimeList = (struct primeList *)NXChunkMalloc(GROW_BY, GROW_BY);
/* we start the list with 2 primes: 2 and 3. */
thePrimeList->numPrimes = 2;
thePrimeList->thePrimes[0] = 2;
thePrimeList->thePrimes[1] = 3;
/*
* start up the primeFinderThread. It will never stop, but we can
* suspend and resume the thread, which is just as good.
*/
primeFinderThread = cthread_fork(findPrimes, 0);
/* since we will never want to join the thread, we detach it. */
cthread_detach(primeFinderThread);
/* create the timed entry that will handle updating the fields */
DPSAddTimedEntry(UPDATE_PERIOD, updateFieldsGlue,
(void *)self, NX_BASETHRESHOLD);
return self;
}
- toggleGoStop:sender
{
/*
* cthread_thread gets us the actual thread, which is a part of
* the cthread structure. struct cthread has a lot of other neat
* stuff in it, too, but we don't (explicitly) use any of it.
* thread_resume() and thread_suspend() just want the thread identifier,
* not a cthread, and we give it to 'em.
*/
if ([sender state] == YES) /* turn it on */
thread_resume(cthread_thread(primeFinderThread));
else /* turn it off */
thread_suspend(cthread_thread(primeFinderThread));
return self;
}
- updateFields
{
/* lock the mutex before reading the list */
mutex_lock(primeListLock);
[numPrimesField setIntValue:thePrimeList->numPrimes];
[highestPrimeField setIntValue:thePrimeList->thePrimes[thePrimeList->numPrimes - 1]];
/* unlock the mutex, now that we're done with the list */
mutex_unlock(primeListLock);
return self;
}
@end